package com.idea.relax.log.listener;


import com.idea.relax.log.constant.ErrorLogConstant;
import com.idea.relax.log.model.ErrorLogModel;
import com.idea.relax.log.props.RelaxLogProperties;
import com.idea.relax.log.publisher.ILogPublisher;
import com.idea.relax.log.service.IErrorLogService;
import com.idea.relax.log.service.IRelaxLogService;
import com.idea.relax.log.support.CallbackMessage;
import com.idea.relax.log.support.AppInfoProvider;
import com.idea.relax.log.support.utils.ExceptionUtil;
import com.idea.relax.log.api.callback.RelaxFailureCallbackHandler;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * @className: ErrorLogListener
 * @description: 错误日志事件的监听
 * @author: salad
 * @date: 2022/10/7
 **/
@Slf4j
@AllArgsConstructor
public class ErrorLogWorker implements Runnable {

    private final ILogPublisher.Wrapper<Map<String, Object>> wrapper;

    private final IErrorLogService errorLogService;

    private final IRelaxLogService relaxLogService;

    private final RelaxLogProperties props;

    private final RelaxFailureCallbackHandler failureCallbackHandler;


    @Override
    public void run() {
        try {
            //存储错误日志
            saveErrorLog();
        } catch (Exception e) {
            Map<String, Object> data = new HashMap<>(16);
            data.put("source", "ErrorLog");
            data.put(ErrorLogConstant.ERR_LOG_MODEL, wrapper.getValue()
                    .get(ErrorLogConstant.ERR_LOG_MODEL));
            CallbackMessage message = new CallbackMessage(Thread.currentThread(), e, data);
           failureCallbackHandler.onException(message);
        }

    }

    private void saveErrorLog() {
        Map<String, Object> values = wrapper.getValue();
        ErrorLogModel model = (ErrorLogModel) values.get(ErrorLogConstant.ERR_LOG_MODEL);
        Throwable error = (Throwable) values.get(ErrorLogConstant.ERROR);
        model.setStackTrace(ExceptionUtil.getStackTraceAsStr(error));
        model.setErrorName(error.getClass().getName());
        model.setErrorMessage(error.getMessage());
        StackTraceElement element = ExceptionUtil.getStackTraceByPrefix(error, props.getErrorLog().getAppPackagePrefix());
        if (null != element) {
            model.setMethodClass(element.getClassName());
            model.setMethodName(element.getMethodName());
            model.setErrorFileName(element.getFileName());
            model.setErrorLineNumber(element.getLineNumber());
        }
        AppInfoProvider.appendServerInfo(model);
        Optional.ofNullable(errorLogService)
                .ifPresent(service -> service.saveErrorLog(model));
        Optional.ofNullable(relaxLogService)
                .ifPresent(service -> service.saveErrorLog(model));
    }

}